package com.zeroes.cons;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.io.InputStream;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Color;
import android.opengl.GLES20;
import android.util.Log;
import android.widget.Toast;
import org.zeroes.svg.*;
import org.zeroes.Events.*;
import org.zeroes.Components.*;
import org.zeroes.common_prelude.*;

import playn.text.Font.Style;
public class ZSGame {
	public static final int LAYER_TYPE_NORMAL=0;
	public static final int LAYER_TYPE_ATLAS=1;
	public boolean caniterateevents=true;
//	public List<ZSSprite> scene ;
	protected Hashtable<String,String> sg; 
	protected List<ZSLayer> Layers;
	protected List<ZSComponent> container;
	public DomParser domparser;
	public int updateRate;
	private boolean onlyonce=false;
	private ZSSprite currentSprite=null;
	public Context ctx;
	public float ldt;
	private float xratio=1.0f;
	private float yratio=1.0f;
	private int dWidth=0;
	private int dHeight=0;
	private boolean theEnd=false;
	protected ZSEventSheet E;
	public ZSGameOptions gameOptions=null;
	private ZSPair<ZSSprite,ZSSprite> spritePair;
//	private ZSRenderer _gl=ZSGameManager.AskMe().GL;;
	public int width=0;
	public int height=0;
	
	public ZSGame(){
	//	scene = Collections.synchronizedList(new ArrayList<ZSSprite>(4));
		Layers = Collections.synchronizedList(new ArrayList<ZSLayer>(4));
		container = Collections.synchronizedList(new ArrayList<ZSComponent>());
		sg= new Hashtable<String,String>();
		updateRate=0;
		

		//

			}
	public ZSGame(ZSGameOptions go){
		this();
		this.gameOptions=go;
	}
	public void initialize(){
		//Log.v("gtrans", "Inceput initializare ... "+this.width);
		ctx=ZSGameManager.AskMe().ctx;
		ConstructoidActivity a = (ConstructoidActivity)ctx;
		this.width=(int)a.getMetrics().width;
		this.height=(int)a.getMetrics().height;
		ZSGameManager.AskMe().setScreenSize(width, height);
		//Log.v("gtrans", "dupa initializare ... "+this.width);
		if(dWidth==0&&dHeight==0)
			this.computeDARatio(width, height);
		//Log.v("gtrans", "id "+R.raw.test1);
		if(gameOptions.gameType==ZSGameManager.GAME_TYPE_SVG_WITH_JAVASCRIPT&&gameOptions.SVGResource>-1)
		{
			initfromSVG(gameOptions.SVGResource);
		}
		E._("*.gameStart.*");
		
	}
	public void initfromSVG(int resource){
		

		InputStream xml = ctx.getResources().openRawResource(resource);
		domparser = new DomParser(xml);
		Log.v("gtrans", "x ratio "+this.getXRatio()+" dWidth "+this.dWidth);
		this.importLayers();
	}
	
	public void runEvents(ZSEventSheet sheet){
		 if(sheet!=null)
		 this.E=sheet;
	 }
	public void addLayer(ZSLayer l){
		if(l!=null)
		{
		Layers.add(l);
		this.makeReorderingDirty();
		this.DirtyforSocialDirty();
		}
	}
	private void importLayers(){
		
		for(SVGElement el: domparser.layers){
			if(el.type==SVGElement.TYPE_BATCH_LAYER){
				
				for(SVGElement nod: domparser.nodes){
					if(nod.type==SVGElement.TYPE_TEXTURE_ATLAS_IMAGE&&nod.parentID.equals(el.id)){
						//new ZSTexture2D(node.imageBytes);
						ZSTexture2D tex=new ZSTexture2D(nod.imageBytes);
						ZSBatchLayer bl =new ZSBatchLayer(el.id,this,tex);
						bl.setTextureLocation(nod.x, nod.y);
						Layers.add(bl);
						
						for(SVGElement r:domparser.rects){
							if(r.type==SVGElement.TYPE_BATCH_LAYER_RECT && r.parentID.equals(el.id)){
								
								//ZSBatchLayer _bl=(ZSBatchLayer) this.getLayerByTitle(el.id);
								bl.addRect(new Rect(r.x-bl.getTexX(),r.y-bl.getTexY(),r.x-bl.getTexX()+r.width,r.y-bl.getTexY()+r.height,r.id));
							}
							
						}
						//this.addLayer(new ZSBatchLayer(el.id,this,new ZSTexture2D(nod.imageBytes)));
					}
					
					if((nod.type==SVGElement.TYPE_TEXTURE_ATLAS_INSTANCE&&nod.parentID.equals(el.id))||nod.type==SVGElement.TYPE_TEXTURE_ATLAS_GROUPEDINSTANCE){
						ZSBatchLayer _bl=(ZSBatchLayer) this.getLayerByTitle(el.id);
						ZSSprite zeS = new ZSSprite(nod.id,_bl.rectById(nod.linkedElem.id));
						zeS.setElement(nod);
						if(nod.type==SVGElement.TYPE_TEXTURE_ATLAS_GROUPEDINSTANCE){
							
							//Log.v("gtrans", "draw from sprite");
							String gid="";
							for(SVGElement _g: domparser.groups){
								if(_g.id.equals(nod.parentID)&&!_g.done)
								{
									_bl.addGroup(_g);
									_g.done=true;
									gid=_g.id;
								}
									
							}
							_bl.addGroupedSprite(zeS,nod.parentID);
							sg.put(nod.id, _bl.title+"."+nod.parentID);	
							
							
						}
						else
						{
						_bl.addSprite(zeS);
						sg.put(nod.id, _bl.title+"."+"freeEntities");
						}
						
						if(nod.trstype==1){
							zeS.setPosition(nod.linkedElem.x+nod.tx+nod.linkedElem.width/2, nod.linkedElem.y+nod.ty+nod.linkedElem.height/2);
							
						}
						else
						{
							Mat3 m3 = new Mat3(nod.td[0],nod.td[1],nod.td[2],nod.td[3],nod.td[4],nod.td[5]);
							float[] poz =m3.applyforPoint(nod.linkedElem.x+nod.linkedElem.width/2, nod.linkedElem.y+nod.linkedElem.height/2);
							zeS.setPosition((int)poz[0],(int)poz[1]);	
							zeS.setRotation(nod.rot);
							zeS.setScale(nod.sx, nod.sy);
						}
						
						
					}
				}
				// clones
				ZSBatchLayer bal=(ZSBatchLayer) this.getLayerByTitle(el.id);
				for(SVGElement c: domparser.clones){
				
					
					ZSSprite _zeS = new ZSSprite(c.id,bal.rectById(c.linkedElem.linkedElem.id));
					if(c.parentID.equals(el.id)){
					bal.addSprite(_zeS);
					sg.put(c.id, bal.title+"."+"freeEntities");
					}
					else
					{
						String gid="";
						for(SVGElement _g: domparser.groups){
							if(_g.id.equals(c.parentID))
							{
								if(!_g.done){
								bal.addGroup(_g);
								_g.done=true;
								}
								gid=_g.id;
							}
								
						}
						bal.addGroupedSprite(_zeS,c.parentID);
						sg.put(c.id, bal.title+"."+c.parentID);
						
					}
					ZSSprite tgs = bal.getSpriteforID(c.linkedElem.id);
					if(c.trstype==1){
						
						_zeS.setPosition(tgs.position.x+c.tx,tgs.position.y+c.ty);
						
					}
					else
					{
						Mat3 _m3 = new Mat3(c.td[0],c.td[1],c.td[2],c.td[3],c.td[4],c.td[5]);
						float[] _poz =_m3.applyforPoint(tgs.position.x, tgs.position.y);
						_zeS.setPosition((int)_poz[0],(int)_poz[1]);	
						_zeS.setRotation(c.rot);
						_zeS.setScale(c.sx, c.sy);
					}
					
				}
				
				
				

				
			}
			else
			{
			this.newLayer(el.id);
			}
		}
		for(SVGElement g: domparser.groups){
			if(!g.parentID.equals("UNKNOWN")&&!g.done)
			{
				this.getLayerByTitle(g.parentID).addGroup(g);
			}
				
		}
		String lt="";
		for(SVGElement n: domparser.nodes){
			if(n.type==SVGElement.TYPE_FREE_IMAGE){
				ZSLayer ll=this.getLayerByTitle(n.parentID);
				ZSSprite _zs=new ZSSprite(n.id);
				_zs.setElement(n);
				ll.addSprite(_zs);
				sg.put(n.id, ll.title+"."+"freeEntities");
			}
			else
			{
				if(n.type==SVGElement.TYPE_GROUPED_IMAGE){
				lt=this.getGroupNamed(n.parentID);
				if(!lt.equals("")){
					ZSLayer ll=this.getLayerByTitle(lt);
					ZSSprite _zs_=new ZSSprite(n.id);
					_zs_.setElement(n);
					ll.addGroupedSprite(_zs_,n.parentID);
					sg.put(n.id, lt+"."+n.parentID);
				}
				}
				}
			
		}
		this.makeReorderingDirty();
		this.DirtyforSocialDirty();
		//this.markTransformDirty();
	}
	protected void changeZOrderOf(ZSSprite sp, int newz){
		
		sp.setZOrder(newz);
		this.makeReorderingDirty();
	}
	
	public void swapLayers(int idx1, int idx2){
		Collections.swap(Layers, idx1, idx2);
		
	}
	public String getGroupNamed(String n){
		
		for(SVGElement g:domparser.groups){
			if(g.id.equals(n)){
				return g.parentID;
				
			}
			
		}
		return "";
	}
	
	public ZSLayer getLayerByTitle(String t){
		if(Layers.size()>0){
		for(ZSLayer l: Layers){
			if(l.title.equals(t)){
				return l;
				
			}
			
		}
		
		}
		return null;
	}
	
	
	public void onTouch(){
		


		
	}
	public void newLayer(String t){
		Layers.add(new ZSLayer(t,this));
		
	}
	
	public void deleteLayer(String lt){
		
		// todo
	}
	public ZSSprite $(String q){
		
		String w=sg.get(q);
		String[] items = w.split("\\.");
		return this.getLayerByTitle(items[0]).getSpriteforID(q);
		
	}
	public void draw(float alpha){
		if(!theEnd){
		for(ZSLayer l: Layers){
			l.visit(alpha);
			
		}
		}
		/*  ZSSprite obj = scene.get(0);
		  obj.visit(alpha);
		  
		  ZSSprite obj1 = scene.get(1);
		  obj1.visit(alpha);	*/
	
	}
	
	public void update(float dt){
		if(onlyonce){
			this.width=(int)ZSGameManager.AskMe().screenSize.width;
			this.height=(int)ZSGameManager.AskMe().screenSize.height;
			this.computeDARatio(width, height);
			onlyonce=false;
			this.initialize();
			ZSGameManager.AskMe().dismissProgressDialog();
		}
		if(!theEnd){
		ldt=dt;
		for(ZSLayer l: Layers){
			l.savepreupdateValues();
			
		}
		//E._("*.tick.*");
		//Log.v("gtrans","width  "+this.width);
		E.makeOnce("sys.tick.*", new Condback(){
			
			public void is(String evn, int i){
				ZSPair<Float,String> rate = new ZSPair<Float,String> (ldt,"");
				ZSEvent ev = new ZSEvent(evn,null,0);
				ev.complements.add(rate);
				E._(evn,ev);
			}
		});
	
		this.tickMadeEvents(dt);
		}
		/*ZSSprite obj = scene.get(0);
		obj.savepreupdateValues();
		  ZSSprite obj1 = scene.get(1);
		  obj1.savepreupdateValues();*/
	}	
	private void tickMadeEvents(float dt){
		//Log.v("gtrans", "tick made events "+dt);
		for(int i=0;i<E.getMadeEventsCount();i++){
			
			E.tickmadeEvent(i,dt);
		}
		
	}
	public void markTransformDirty(){
	//	int[] sz = ZSGameManager.AskMe().winSize();
	
		width=ZSGameManager.AskMe().GL.mWidth;
		height=ZSGameManager.AskMe().GL.mHeight;
		
		for(ZSLayer l: Layers){
			l.markTransformDirty();
			
		}

	}
	
	public void makeReorderingDirty(){
		
		for(ZSLayer l: Layers){
			l.DirtytoOrderingDirty();
			
		}

	}
	public void DirtyforSocialDirty(){
		
		for(ZSLayer l: Layers){
			l.SocialDirty=true;
			
		}
		
	}
	
	public void setCurrentSprite(ZSSprite _s){
		this.currentSprite=_s;
		
	}
	public ZSSprite getCurrentSprite(){
		
		return this.currentSprite;
	}
	
	public void buildCollisionEventFor(String firstSpriteTag, String secondSpriteTag){
		ZSSprite fs =$(firstSpriteTag);
		ZSSprite ss =$(secondSpriteTag);
		if(fs!=null&&ss!=null){
		spritePair= new ZSPair<ZSSprite,ZSSprite> (fs,ss);
		E.make(firstSpriteTag+".collideWith."+secondSpriteTag, new Condback(){
			
			public void is(String evName, int idx){
				
			if(spritePair.getFirst().getTransformedQuad().intersects_quad(spritePair.getSecond().getTransformedQuad())){
				ZSEvent ev = new ZSEvent(evName,spritePair,0);
				E._(evName, ev);
			}
			}
		});
		}
	}
	public void registerComponent(ZSComponent aComponent){
		if(aComponent!=null&&!this.hasComponentNamed(aComponent.name))
		this.container.add(aComponent);
	}
	
	public List<ZSComponent> getContainer(){
		
		return this.container;
	}
	
	public boolean hasComponentNamed(String n){
		
		for(ZSComponent c : this.container){
			
			if(c.name.equals(n))
				return true;
		}
		
		return false;
	}
public int getComponentCount(){
	
	return this.container.size();
}

public void EndLevel(String levelID){
	
			this.onlyonce=true;
			E._("sys.EndLevel."+levelID,null);
			
}

public void clearAll(){
	//theEnd=true;
  //  GLES20.glClearColor(1.0f, 1.0f, 0.23f, 1.0f);
    
  //  GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
	/*for(ZSLayer l: Layers){
		l.hide();
		//l.removeAllSprites();
	}*/
	Set<String> keys=sg.keySet();
	   Iterator iter = keys.iterator();
	    while (iter.hasNext()) {
	      String item =(String)iter.next();
	      
	      String w=sg.get(item);
			String[] items = w.split("\\.");
			ZSLayer layer = (ZSLayer)this.getLayerByTitle(items[0]);
			ZSSprite spr = (ZSSprite) layer.getSpriteforID(item);
			//Log.v("gtrans", item+" are tex ID "+spr.getTextureID());
			if(spr!=null){
			layer.removeSprite(spr);
			spr.unloadTexture();
			}
		//	return this.getLayerByTitle(items[0]).getSpriteforID(q);
	    }
	
		
	   /* ZSLabel txt = new ZSLabel("LOADING .... ",Style.ITALIC,52,Color.BLUE,100.0f);
	    txt.tag="";
	   this.getLayerByTitle("Background").addSprite(txt);
	 
	    txt.setPosition(500, 300);*/
	
	//Layers.clear();
//	container.clear();
//	sg.clear();
	//System.err.println("Curatenie ...  ");
}

public void StartNewLevel(){
	this.onlyonce=true;
	
}

public void assetReload(){
	
	Set<String> keys=sg.keySet();
	   Iterator iter = keys.iterator();
	    while (iter.hasNext()) {
	      String item =(String)iter.next();
	      
	      String w=sg.get(item);
			String[] items = w.split("\\.");
			ZSLayer layer = (ZSLayer)this.getLayerByTitle(items[0]);
			ZSSprite spr = (ZSSprite) layer.getSpriteforID(item);
			if(layer.type==ZSGame.LAYER_TYPE_ATLAS){
				//Log.v("gtrans","batch layer processed "+layer.title);
				ZSBatchLayer bl = (ZSBatchLayer)layer;
				bl.reloadTexture();
			}
			//Log.v("gtrans", item+" are tex ID "+spr.getTextureID());
			if(spr!=null)
			spr.reloadTexture();
		//	return this.getLayerByTitle(items[0]).getSpriteforID(q);
	    }
	    
}

public void computeDARatio(int _w,int _h){
this.dWidth=_w;
this.dHeight=_h;

if(width>0&&height>0){
	xratio=(float)width/dWidth;
	yratio=(float)height/dHeight;	
}
}

public float getXRatio(){
	return this.xratio;
}
public float getYRatio(){
	return this.yratio;
}
}
